home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Cream of the Crop 3
/
Cream of the Crop 3.iso
/
utility
/
mu17_ext.zip
/
RLHANDLE.C
< prev
next >
Wrap
C/C++ Source or Header
|
1994-03-07
|
17KB
|
585 lines
/*
** $VER: rlhandler.c 1.1 (08.02.94)
**
** rlogin.service handler
**
** ⌐ Copyright 1994 by Norbert Pⁿschel
** All Rights Reserved
*/
#include <proto/exec.h>
#include <proto/dos.h>
#include <proto/utility.h>
#include <proto/multiuser.h>
#include <clib/accounts_protos.h>
#include <pragmas/accounts_pragmas.h>
#include <clib/nipc_protos.h>
#include <pragmas/nipc_pragmas.h>
#include <clib/alib_stdio_protos.h>
#include <envoy/errors.h>
#include <exec/alerts.h>
#include <exec/memory.h>
#include <dos/var.h>
#include <dos/dostags.h>
#include <dos/dosextens.h>
#include <devices/conunit.h>
#include <string.h>
#include <debug.h>
#define GVB GVF_LOCAL_ONLY|GVF_BINARY_VAR|GVF_DONT_NULL_TERM
#define tp_size sizeof(struct Task *)
#define pp_size sizeof(struct MsgPort *)
#define req(trans,n) (void *)(((UBYTE *)(trans->trans_RequestData))+(n))
#define resp(trans,n) (void *)(((UBYTE *)(trans->trans_ResponseData))+(n))
#define OFFS_CONUNIT 0
#define SIZE_CONUNIT 14*sizeof(WORD)
#define OFFS_RES1 OFFS_CONUNIT+SIZE_CONUNIT
#define SIZE_RES1 sizeof(LONG)
#define OFFS_RES2 OFFS_RES1+SIZE_RES1
#define SIZE_RES2 sizeof(LONG)
#define OFFS_RESPDATA OFFS_RES2+SIZE_RES2
#define OFFS_ARG1 0
#define SIZE_ARG1 sizeof(LONG)
#define OFFS_ARG2 OFFS_ARG1+SIZE_ARG1
#define SIZE_ARG2 sizeof(LONG)
#define OFFS_REQDATA OFFS_ARG2+SIZE_ARG2
#define CONUNIT(ci) (APTR)&(((struct ConUnit *)((ci)->ci_IOStdReq->io_Unit))->cu_XCP)
extern volatile ULONG NumProcs;
#define CFGBUFFLEN 256
#define CBUFFLEN 2*CFGBUFFLEN+80
/* rshell startup packet:
Arg1 = user name
Arg2 = password
Arg3 = host name
Arg4 = handler port
*/
void __saveds rshell_func(void)
{
struct muBase *muBase;
struct MsgPort *handler_port;
struct FileHandle *fh;
BPTR bfh;
UBYTE cbuff[CBUFFLEN];
UBYTE cfg[CFGBUFFLEN];
struct Message *msg;
struct DosPacket *dp;
Forbid();
NumProcs++;
Permit();
handler_port = &(((struct Process *)FindTask(0))->pr_MsgPort);
WaitPort(handler_port);
msg = GetMsg(handler_port); /* get startup message */
if(msg == 0 || (dp = (struct DosPacket *)(msg->mn_Node.ln_Name)) == 0) {
Alert(AN_Unknown);
Wait(0); /* not much that I can do here */
}
handler_port = (struct MsgPort *)(dp->dp_Arg4);
strcpy(cbuff,"Execute S:Shell-Startup\n");
muBase = (struct muBase *)OpenLibrary(MULTIUSERNAME,MULTIUSERVERSION);
if(muBase) {
if(muGetTaskOwner(0)) {
muLogout(muT_All,TRUE,muT_Quiet,TRUE,TAG_DONE);
}
if(Stricmp((STRPTR)(dp->dp_Arg1),"Nobody")) {
if(muLogin(muT_UserID,(STRPTR)(dp->dp_Arg1),
muT_Password,(STRPTR)(dp->dp_Arg2),
TAG_DONE)) {
bfh = muGetConfigDirLock();
if(bfh) {
if(NameFromLock(bfh,cfg,CFGBUFFLEN) &&
AddPart(cfg,muProfile_FileName,CFGBUFFLEN)) {
strcat(cbuff,"If EXISTS ");
strcat(cbuff,cfg);
strcat(cbuff,"\nExecute ");
strcat(cbuff,cfg);
strcat(cbuff,"\nEndIf\n");
}
UnLock(bfh);
}
}
}
CloseLibrary((struct Library *)muBase);
}
fh = 0;
if(SetVar("REMOTE",(STRPTR)(dp->dp_Arg3),-1,0)) {
fh = (struct FileHandle *)AllocDosObjectTags(DOS_FILEHANDLE,TAG_END);
if(fh) {
dp->dp_Res1 = DOSTRUE;
PutMsg(dp->dp_Port,msg);
fh->fh_Type = handler_port;
bfh = MKBADDR(fh);
if(DoPkt3(handler_port,ACTION_FINDOUTPUT,bfh,0,0)) {
Execute(cbuff,bfh,0);
DoPkt1(handler_port,ACTION_END,fh->fh_Arg1);
}
FreeDosObject(DOS_FILEHANDLE,fh);
}
}
if(fh == 0) {
dp->dp_Res1 = DOSFALSE;
dp->dp_Res2 = ENVOYERR_NORESOURCES;
PutMsg(dp->dp_Port,msg);
}
Forbid();
NumProcs--;
}
struct ConInfo {
struct MinList ci_Actions;
LONG ci_OpenCnt;
LONG ci_NextKey;
struct Entity *ci_Dest;
struct Entity *ci_Source;
struct MsgPort *ci_Handler;
struct MsgPort *ci_Break;
struct IOStdReq *ci_IOStdReq;
};
void do_packet(struct Library *NIPCBase,
struct ConInfo *ci,
struct DosPacket *dp);
void do_transaction(struct Library *NIPCBase,
struct ConInfo *ci,
struct Transaction *trans);
/* handler startup packet:
Arg1 = user name
Arg2 = password
Arg3 = host name
Arg4 = entity name buffer
*/
void __saveds handler_func(void)
{
struct Library *NIPCBase;
struct ConInfo ci;
struct Process *rshell;
ULONG entsignum;
struct Transaction *trans;
struct Message *msg;
struct DosPacket *dp;
UBYTE uname[32];
UBYTE pwd[16];
UBYTE hname[128];
ULONG mask;
Forbid();
NumProcs++;
Permit();
ci.ci_Handler = &(((struct Process *)FindTask(0))->pr_MsgPort);
WaitPort(ci.ci_Handler);
msg = GetMsg(ci.ci_Handler); /* get startup message */
if(msg == 0 || (dp = (struct DosPacket *)(msg->mn_Node.ln_Name)) == 0) {
Alert(AN_Unknown);
Wait(0); /* not much that I can do here */
}
strcpy(uname,(STRPTR)(dp->dp_Arg1));
strcpy(pwd,(STRPTR)(dp->dp_Arg2));
strcpy(hname,(STRPTR)(dp->dp_Arg3));
debug("Handler\n");
ci.ci_Source = 0; /* because we use it as flag */
NIPCBase = OpenLibrary("nipc.library",39);
if(NIPCBase) {
ci.ci_Handler = CreateMsgPort();
if(ci.ci_Handler) {
sprintf((STRPTR)(dp->dp_Arg4),"RHandler_%ld",FindTask(0));
ci.ci_Source = CreateEntity(ENT_Name,dp->dp_Arg4,
ENT_Public,TRUE,
ENT_AllocSignal,&entsignum,
TAG_DONE);
if(ci.ci_Source) {
debug("Handler Entity created\n"); /* now we have to reply */
dp->dp_Res1 = DOSTRUE;
PutMsg(dp->dp_Port,msg);
debug2("Waiting for Startup-Transaction: %ld\n",entsignum);
do {
Wait(1L<<entsignum); /* wait for startup transaction */
trans = GetTransaction(ci.ci_Source);
} while(trans == 0);
if(trans->trans_Command > 1) {
trans->trans_Error = ENVOYERR_CMDUNKNOWN;
ci.ci_Dest = 0;
}
else {
if(trans->trans_Command == 1) {
ci.ci_IOStdReq = (struct IOStdReq *)
AllocMem(sizeof(struct IOStdReq),MEMF_PUBLIC|MEMF_CLEAR);
if(ci.ci_IOStdReq) {
ci.ci_IOStdReq->io_Unit = (struct Unit *)
AllocMem(sizeof(struct ConUnit),MEMF_PUBLIC|MEMF_CLEAR);
if(ci.ci_IOStdReq->io_Unit) {
CopyMem(req(trans,OFFS_CONUNIT),CONUNIT(&ci),SIZE_CONUNIT);
}
else {
FreeMem(ci.ci_IOStdReq,sizeof(struct IOStdReq));
ci.ci_IOStdReq = 0;
}
}
}
else ci.ci_IOStdReq = 0;
debug2("IOStdReq: %ld\n",(LONG)(ci.ci_IOStdReq));
ci.ci_Dest = FindEntity(*hname ? hname : 0,
(STRPTR)req(trans,SIZE_CONUNIT),ci.ci_Source,
&(trans->trans_Error));
}
ReplyTransaction(trans);
if(ci.ci_Dest) {
debug("Remote Entity detected\n");
rshell = CreateNewProcTags(NP_Entry,rshell_func,
NP_Name,"Remote Shell Executor",
NP_Priority,0,
NP_WindowPtr,-1,
NP_Cli,TRUE,
TAG_DONE);
if(rshell) {
debug("Remote Shell Created\n");
if(DoPkt4(&(rshell->pr_MsgPort),0,(LONG)uname,(LONG)pwd,
(LONG)hname,(LONG)ci.ci_Handler)) {
NewList((struct List *)&(ci.ci_Actions));
ci.ci_OpenCnt = 0;
ci.ci_NextKey = 0;
ci.ci_Break = &(rshell->pr_MsgPort);
debug("Starting Loop\n");
mask = (1L<<ci.ci_Handler->mp_SigBit)|(1L<<entsignum);
do {
Wait(mask);
do {
if(trans = GetTransaction(ci.ci_Source)) {
do_transaction(NIPCBase,&ci,trans);
}
if(msg = GetMsg(ci.ci_Handler)) {
dp = (struct DosPacket *)(msg->mn_Node.ln_Name);
do_packet(NIPCBase,&ci,dp);
}
} while(msg != 0 || trans != 0);
} while(ci.ci_OpenCnt > 0 ||
!IsListEmpty((struct List *)&(ci.ci_Actions)));
debug("Ending Loop\n");
trans = AllocTransaction(TAG_DONE);
if(trans) {
trans->trans_Command = 1;
DoTransaction(ci.ci_Dest,ci.ci_Source,trans);
FreeTransaction(trans);
}
}
}
LoseEntity(ci.ci_Dest);
}
if(ci.ci_IOStdReq) {
if(ci.ci_IOStdReq->io_Unit) {
FreeMem(ci.ci_IOStdReq->io_Unit,sizeof(struct ConUnit));
}
FreeMem(ci.ci_IOStdReq,sizeof(struct IOStdReq));
}
DeleteEntity(ci.ci_Source);
}
DeleteMsgPort(ci.ci_Handler);
}
CloseLibrary(NIPCBase);
}
debug("Ending Handler\n");
if(ci.ci_Source == 0) {
dp->dp_Res1 = DOSFALSE;
dp->dp_Res2 = ENVOYERR_NORESOURCES;
PutMsg(dp->dp_Port,msg);
}
Forbid();
NumProcs--;
}
struct ActionNode {
struct MinNode an_Node;
struct DosPacket *an_Packet;
struct Transaction *an_Trans;
};
void do_packet(struct Library *NIPCBase,
struct ConInfo *ci,
struct DosPacket *dp)
{
struct ActionNode *an;
struct Transaction *trans;
struct FileHandle *fh;
struct MsgPort *rport;
LONG temp;
debug2("Received Packet: %ld\n",dp->dp_Type);
switch(dp->dp_Type) {
case ACTION_FINDUPDATE:
case ACTION_FINDINPUT:
case ACTION_FINDOUTPUT:
fh = BADDR(dp->dp_Arg1);
fh->fh_Port = (struct MsgPort *)DOSTRUE;
fh->fh_Arg1 = ci->ci_NextKey++;
ci->ci_OpenCnt++;
dp->dp_Res1 = DOSTRUE;
ci->ci_Break = dp->dp_Port;
dp->dp_Port = ci->ci_Handler;
PutMsg(ci->ci_Break,dp->dp_Link);
debug2("Open: %d\n",ci->ci_OpenCnt);
return;
case ACTION_END:
debug2("Close: %ld\n",dp->dp_Arg1);
an = (struct ActionNode *)(ci->ci_Actions.mlh_Head);
while(an->an_Node.mln_Succ) {
temp = an->an_Packet->dp_Type;
if(temp != ACTION_SCREEN_MODE && temp != ACTION_WAIT_CHAR &&
an->an_Packet->dp_Arg1 == dp->dp_Arg1) {
AbortTransaction(an->an_Trans);
WaitTransaction(an->an_Trans);
FreeTransaction(an->an_Trans);
if(temp == ACTION_READ || temp == ACTION_WRITE) {
an->an_Packet->dp_Res1 = -1;
}
else {
an->an_Packet->dp_Res1 = DOSFALSE;
}
an->an_Packet->dp_Res2 = ERROR_INVALID_LOCK;
rport = an->an_Packet->dp_Port;
an->an_Packet->dp_Port = ci->ci_Handler;
PutMsg(rport,an->an_Packet->dp_Link);
temp = (LONG)(an->an_Node.mln_Succ);
Remove((struct Node *)an);
FreeMem(an,sizeof(struct ActionNode));
an = (struct ActionNode *)temp;
}
else {
an = (struct ActionNode *)(an->an_Node.mln_Succ);
}
}
ci->ci_OpenCnt--;
dp->dp_Res1 = DOSTRUE;
rport = dp->dp_Port;
dp->dp_Port = ci->ci_Handler;
PutMsg(rport,dp->dp_Link);
return;
case ACTION_READ:
an = (struct ActionNode *)AllocMem(sizeof(struct ActionNode),0);
if(an) {
trans = AllocTransaction(TRN_AllocReqBuffer,
OFFS_REQDATA,
TRN_AllocRespBuffer,
OFFS_RESPDATA+dp->dp_Arg3,
TAG_DONE);
if(trans) {
*(LONG *)req(trans,OFFS_ARG1) = ACTION_READ;
*(LONG *)req(trans,OFFS_ARG2) = dp->dp_Arg3;
BeginTransaction(ci->ci_Dest,ci->ci_Source,trans);
an->an_Trans = trans;
an->an_Packet = dp;
AddTail((struct List *)&(ci->ci_Actions),(struct Node *)an);
return;
}
FreeMem(an,sizeof(struct ActionNode));
}
dp->dp_Res1 = -1;
goto nomem2;
case ACTION_WRITE:
case 2001: /* ACTION_FORCE */
case 2002: /* ACTION_STACK */
case 2003: /* ACTION_QUEUE */
an = (struct ActionNode *)AllocMem(sizeof(struct ActionNode),0);
if(an) {
trans = AllocTransaction(TRN_AllocReqBuffer,
OFFS_REQDATA+dp->dp_Arg3,
TRN_AllocRespBuffer,
OFFS_RESPDATA,
TAG_DONE);
if(trans) {
*(LONG *)req(trans,OFFS_ARG1) = dp->dp_Type;
*(LONG *)req(trans,OFFS_ARG2) = dp->dp_Arg3;
CopyMem((APTR)(dp->dp_Arg2),req(trans,OFFS_REQDATA),dp->dp_Arg3);
BeginTransaction(ci->ci_Dest,ci->ci_Source,trans);
an->an_Trans = trans;
an->an_Packet = dp;
AddTail((struct List *)&(ci->ci_Actions),(struct Node *)an);
return;
}
FreeMem(an,sizeof(struct ActionNode));
}
if(dp->dp_Type == ACTION_WRITE) {
dp->dp_Res1 = -1;
goto nomem2;
}
break;
case ACTION_SEEK:
dp->dp_Res1 = -1;
dp->dp_Res2 = ERROR_ACTION_NOT_KNOWN;
rport = dp->dp_Port;
dp->dp_Port = ci->ci_Handler;
PutMsg(rport,dp->dp_Link);
return;
case ACTION_WAIT_CHAR:
case ACTION_SCREEN_MODE:
case 2004: /* ACTION_DROP */
an = (struct ActionNode *)AllocMem(sizeof(struct ActionNode),0);
if(an) {
trans = AllocTransaction(TRN_AllocReqBuffer,
OFFS_REQDATA,
TRN_AllocRespBuffer,
OFFS_RESPDATA,
TAG_DONE);
if(trans) {
*(LONG *)req(trans,OFFS_ARG1) = dp->dp_Type;
*(LONG *)req(trans,OFFS_ARG2) = dp->dp_Arg1;
BeginTransaction(ci->ci_Dest,ci->ci_Source,trans);
an->an_Trans = trans;
an->an_Packet = dp;
AddTail((struct List *)&(ci->ci_Actions),(struct Node *)an);
return;
}
FreeMem(an,sizeof(struct ActionNode));
}
break;
case ACTION_CHANGE_SIGNAL:
dp->dp_Res1 = DOSTRUE;
dp->dp_Res2 = (LONG)(ci->ci_Break);
if(dp->dp_Arg2) {
ci->ci_Break = (struct MsgPort *)dp->dp_Arg2;
}
rport = dp->dp_Port;
dp->dp_Port = ci->ci_Handler;
PutMsg(rport,dp->dp_Link);
return;
case ACTION_DISK_INFO:
if(ci->ci_IOStdReq) {
struct InfoData *id;
ULONG i;
id = (struct InfoData *)BADDR(dp->dp_Arg1);
for(i = 0;i < sizeof(struct InfoData);i++) ((UBYTE *)id)[i] = 0;
id->id_InUse = (LONG)(ci->ci_IOStdReq);
dp->dp_Res1 = DOSTRUE;
rport = dp->dp_Port;
dp->dp_Port = ci->ci_Handler;
PutMsg(rport,dp->dp_Link);
return;
}
default:
dp->dp_Res1 = DOSFALSE;
dp->dp_Res2 = ERROR_ACTION_NOT_KNOWN;
rport = dp->dp_Port;
dp->dp_Port = ci->ci_Handler;
PutMsg(rport,dp->dp_Link);
return;
}
dp->dp_Res1 = DOSFALSE;
nomem2:
dp->dp_Res2 = ERROR_NO_FREE_STORE;
rport = dp->dp_Port;
dp->dp_Port = ci->ci_Handler;
PutMsg(rport,dp->dp_Link);
}
void do_transaction(struct Library *NIPCBase,
struct ConInfo *ci,
struct Transaction *trans)
{
struct ActionNode *an;
struct DosPacket *dp;
debug3("Transaction: Type: %ld, Com: %ld\n",trans->trans_Type,
trans->trans_Command);
if(trans->trans_Type != TYPE_RESPONSE) {
if(trans->trans_Command > 15) {
trans->trans_Error = ENVOYERR_CMDUNKNOWN;
}
else {
debug2("BREAK: %ld\n",trans->trans_Command);
if((ci->ci_Break->mp_Flags & PF_ACTION) == PA_SIGNAL) {
Signal(ci->ci_Break->mp_SigTask,((ULONG)(trans->trans_Command))<<12);
debug("BREAK done\n");
}
}
ReplyTransaction(trans);
}
else {
an = (struct ActionNode *)(ci->ci_Actions.mlh_Head);
while(an->an_Node.mln_Succ) {
if(an->an_Trans == trans) break;
an = (struct ActionNode *)(an->an_Node.mln_Succ);
}
if(an->an_Node.mln_Succ) {
dp = an->an_Packet;
if(trans->trans_Error) {
if(dp->dp_Type == ACTION_READ || dp->dp_Type == ACTION_WRITE) {
dp->dp_Res1 = -1;
}
else {
dp->dp_Res1 = DOSFALSE;
}
dp->dp_Res2 = ERROR_NO_FREE_STORE;
}
else {
if(ci->ci_IOStdReq) {
CopyMem(resp(trans,OFFS_CONUNIT),CONUNIT(ci),SIZE_CONUNIT);
}
dp->dp_Res1 = *(LONG *)resp(trans,OFFS_RES1);
dp->dp_Res2 = *(LONG *)resp(trans,OFFS_RES2);
if(dp->dp_Type == ACTION_READ && dp->dp_Res1 > 0) {
CopyMem(resp(trans,OFFS_RESPDATA),(APTR)(dp->dp_Arg2),dp->dp_Res1);
}
}
ci->ci_Break = dp->dp_Port;
dp->dp_Port = ci->ci_Handler;
PutMsg(ci->ci_Break,dp->dp_Link);
Remove((struct Node *)an);
FreeMem(an,sizeof(struct ActionNode));
}
FreeTransaction(trans);
}
}